/**************************************************************************************************
 * Copyright (c) 2021 Calypso Networks Association https://calypsonet.org/                        *
 *                                                                                                *
 * See the NOTICE file(s) distributed with this work for additional information regarding         *
 * copyright ownership.                                                                           *
 *                                                                                                *
 * This program and the accompanying materials are made available under the terms of the Eclipse  *
 * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0                  *
 *                                                                                                *
 * SPDX-License-Identifier: EPL-2.0                                                               *
 **************************************************************************************************/

#pragma once

#include <string>
#include <sstream>

namespace keyple {
namespace core {
namespace util {
namespace cpp {

class StringBuilder {
private:
    std::string privateString;

public:
    StringBuilder() {}

    explicit StringBuilder(const std::string& initialString) : privateString(initialString) {}

    explicit StringBuilder(std::size_t capacity)
    {
        ensureCapacity(capacity);
    }

    char charAt(std::size_t index)
    {
        return privateString[index];
    }

    StringBuilder* append(const std::string& toAppend)
    {
        privateString += toAppend;
        return this;
    }

    template <typename T> StringBuilder* append(const T& toAppend)
    {
        privateString += toString(toAppend);
        return this;
    }

    StringBuilder* insert(std::size_t position, const std::string& toInsert)
    {
        privateString.insert(position, toInsert);
        return this;
    }

    template <typename T>
    StringBuilder* insert(std::size_t position, const T& toInsert)
    {
        privateString.insert(position, toString(toInsert));
        return this;
    }

    std::string toString()
    {
        return privateString;
    }

    std::size_t length()
    {
        return privateString.length();
    }

    void setLength(std::size_t newLength)
    {
        privateString.resize(newLength);
    }

    std::size_t capacity()
    {
        return privateString.capacity();
    }

    void ensureCapacity(std::size_t minimumCapacity)
    {
        privateString.reserve(minimumCapacity);
    }

    StringBuilder* remove(std::size_t start, std::size_t end)
    {
        privateString.erase(start, end - start);
        return this;
    }

    StringBuilder* replace(std::size_t start, std::size_t end,
                           const std::string& newString)
    {
        privateString.replace(start, end - start, newString);
        return this;
    }

private:
    template <typename T> static std::string toString(const T& subject)
    {
        std::ostringstream ss;
        ss << subject;
        return ss.str();
    }
};

}
}
}
}
